/*-------------------------------------------------------------------------
 *
 * quote.c
 *	  Functions for quoting identifiers and literals
 *
 * Portions Copyright (c) 2000-2022, PostgreSQL Global Development Group
 *
 *
 * IDENTIFICATION
 *	  src/backend/utils/adt/quote.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "utils/builtins.h"


/*
 * quote_ident -
 *	  返回一个适当引用的标识符
 */
Datum quote_ident(PG_FUNCTION_ARGS)
{
	text	   *fc_t = PG_GETARG_TEXT_PP(0);
	const char *fc_qstr;
	char	   *fc_str;

	fc_str = text_to_cstring(fc_t);
	fc_qstr = quote_identifier(fc_str);
	PG_RETURN_TEXT_P(cstring_to_text(fc_qstr));
}

/*
 * quote_literal_internal -
 *	  quote_literal 和 quote_literal_cstr 的辅助函数
 *
 * 注意：请不要让此函数的行为随
 * standard_conforming_strings 而变化。我们不知道结果
 * 字面量将在哪里使用，因此必须生成一个
 * 对于任何设置都能工作的结果。在认为自己更聪明之前，看看 dblink
 * 是如何利用它的。
 */
static size_t fc_quote_literal_internal(char *fc_dst, const char *fc_src, size_t fc_len)
{
	const char *fc_s;
	char	   *fc_savedst = fc_dst;

	for (fc_s = fc_src; fc_s < fc_src + fc_len; fc_s++)
	{
		if (*fc_s == '\\')
		{
			*fc_dst++ = ESCAPE_STRING_SYNTAX;
			break;
		}
	}

	*fc_dst++ = '\'';
	while (fc_len-- > 0)
	{
		if (SQL_STR_DOUBLE(*fc_src, true))
			*fc_dst++ = *fc_src;
		*fc_dst++ = *fc_src++;
	}
	*fc_dst++ = '\'';

	return fc_dst - fc_savedst;
}

/*
 * quote_literal -
 *	  返回一个适当引用的字面量
 */
Datum quote_literal(PG_FUNCTION_ARGS)
{
	text	   *fc_t = PG_GETARG_TEXT_PP(0);
	text	   *fc_result;
	char	   *fc_cp1;
	char	   *fc_cp2;
	int			fc_len;

	fc_len = VARSIZE_ANY_EXHDR(fc_t);
	/* 我们创建一个最坏情况的结果区域；浪费一点空间是可以的 */
	fc_result = (text *) palloc(fc_len * 2 + 3 + VARHDRSZ);

	fc_cp1 = VARDATA_ANY(fc_t);
	fc_cp2 = VARDATA(fc_result);

	SET_VARSIZE(fc_result, VARHDRSZ + fc_quote_literal_internal(fc_cp2, fc_cp1, fc_len));

	PG_RETURN_TEXT_P(fc_result);
}

/*
 * quote_literal_cstr -
 *	  返回一个适当引用的字面量
 */
char * quote_literal_cstr(const char *fc_rawstr)
{
	char	   *fc_result;
	int			fc_len;
	int			fc_newlen;

	fc_len = strlen(fc_rawstr);
	/* 我们创建一个最坏情况的结果区域；浪费一点空间是可以的 */
	fc_result = palloc(fc_len * 2 + 3 + 1);

	fc_newlen = fc_quote_literal_internal(fc_result, fc_rawstr, fc_len);
	fc_result[fc_newlen] = '\0';

	return fc_result;
}

/*
 * quote_nullable -
 *	  返回一个适当引用的字面量，将空值返回
 *	  为文本字符串 'NULL'。
 */
Datum quote_nullable(PG_FUNCTION_ARGS)
{
	if (PG_ARGISNULL(0))
		PG_RETURN_TEXT_P(cstring_to_text("NULL"));
	else
		PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
											PG_GETARG_DATUM(0)));
}
